package com.cooqe.collection_ping.utils;

import com.cooqe.collection_ping.model.Target;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.SystemUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 折戟沉沙铁未销
 * @version V1.0
 * @date 2023/11/14-2023
 * @Description: snmp util 工具类
 */
@Slf4j
@SuppressWarnings("all")
public class PingUtil_bak {

    private static final Pattern LINUX_SUMMARY = Pattern.compile("(\\d+)%(?: min/avg/max/mdev = (\\S+)/(\\S+)/(\\S+)/(\\S+))?");
    //private static final Pattern LINUX_SUMMARY = Pattern.compile("(\\d+)%");
    private static final Pattern WINDOWS_ALIVE = Pattern.compile("Reply\\[\\d+\\] from (\\S+): bytes=\\d+ time=(\\S+) ms TTL=\\d+");


    /**
     * 判断操作系统是否是win
     * @return
     */
    public static Boolean isWinSystem() {
        if (SystemUtils.IS_OS_WINDOWS) {
            return true;
        }
        return false;
    }

    /**
     * 不同的操作系统，ping 命令参数有部分不同。根据当前环境的操作系统，执行不同的ping 命令
     * @param targets
     */
    public static void executePing(List<Target> targets) {
        if (SystemUtils.IS_OS_WINDOWS) {
            pingWin(targets);
        }
        pingLinux(targets);
    }


    /**
     * win 系统 执行ping 操作
     * @param targets
     * @return
     */
    public static List<Target> pingWin(List<Target> targets) {
        Map<Target, String> handleMap = new HashMap<>();
        Map<String, Target> targetMap = new HashMap<>();
        Map<String, ArrayList<Double>> dataMap = new HashMap<>();
        for (Target target : targets) {
            String pingCommand = "ping -n " + target.getRetry() + " -w " + target.getTimeout() + " " + target.getIp();
            handleMap.put(target, pingCommand);
            dataMap.put(target.getIp(), new ArrayList<Double>());
            targetMap.put(target.getIp(), target);
        }
        Set<Target> sets = handleMap.keySet();
        try {
            //ping 获取数据
            for (Target target : sets) {
                String pingCommand = handleMap.get(target);
                Process process = Runtime.getRuntime().exec(pingCommand);
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("时间=")) {
                        int startIndex = line.indexOf("时间=") + 3;
                        int endIndex = line.indexOf("ms");
                        double responseTime = Double.parseDouble(line.substring(startIndex, endIndex).trim());
                        System.out.println(responseTime);
                        ArrayList<Double> data = dataMap.get(target.getIp());
                        data.add(responseTime);
                    }
                }
            }
            //解析计算数据
            for (Map.Entry<String, ArrayList<Double>> entry : dataMap.entrySet()) {
                String ip = entry.getKey();
                ArrayList<Double> rawDataList = entry.getValue();
                Target target = targetMap.get(ip);
                target.setLastExecuteTime(System.currentTimeMillis());
                if (rawDataList.isEmpty()) {
                    target.decreaseHealth();
                } else {
                    double sum = 0;
                    int count = rawDataList.size();
                    for (double rawData : rawDataList) {
                        sum += rawData;
                    }
                    double avg = sum / count;
                    double jitter = 0;
                    for (double rawData : rawDataList) {
                        jitter += Math.pow(rawData - avg, 2);
                    }
                    jitter = Math.pow(jitter / count, 0.5);
                    target.restoreHealth();
                    target.setLatency((int) avg);
                    target.setPacketLoss((target.getRetry() - count) * 100 / count);
                    target.setJitter((int) jitter);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return targets;
        }
    }


    /**
     * linux 执行ping 操作
     * @param targets
     * @return
     */
    public static List<Target> pingLinux(List<Target> targets) {
        Map<Target, String> handleMap = new HashMap<>();
        Map<String, Target> targetMap = new HashMap<>();
        Map<String, ArrayList<Double>> dataMap = new HashMap<>();
        for (Target target : targets) {
            String pingCommand = "ping -c " + target.getRetry() + " -W " + target.getTimeout() + " " + target.getIp();
            handleMap.put(target, pingCommand);
            dataMap.put(target.getIp(), new ArrayList<Double>());
            targetMap.put(target.getIp(), target);
        }
        Set<Target> sets = handleMap.keySet();
        try {
            //ping 获取数据
            for (Target target : sets) {
                String pingCommand = handleMap.get(target);
                Process process = Runtime.getRuntime().exec(pingCommand);
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
                String line;
                while ((line = reader.readLine()) != null) {
                    System.err.println(line);
                    Matcher matcher = LINUX_SUMMARY.matcher(line);
                    if (matcher.find()) {
                        try {
                            if (target != null) {
                                target.setLastExecuteTime(System.currentTimeMillis());
                                int packetLoss = Integer.valueOf(matcher.group(2));

                                if (packetLoss == 100) {
                                    target.decreaseHealth();
                                } else {
                                    double min = Double.valueOf(matcher.group(3));
                                    double avg = Double.valueOf(matcher.group(4));
                                    double max = Double.valueOf(matcher.group(5));
                                    target.restoreHealth();
                                    target.setPacketLoss(packetLoss);
                                    target.setLatency((int) avg);
                                    target.setJitter((int) Math.sqrt((Math.pow(avg - min, 2) + Math.pow(max - avg, 2)) / 2));
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return targets;
        }
    }

    public static void main(String[] args) {
        List<Target> dataList = new ArrayList<>();
        Target target = new Target("192.168.1.30", 3000, 3);
        dataList.add(target);
        //pingWin(dataList);
        pingLinux(dataList);


        /*String input = "4 packets transmitted, 4 received, 0% packet loss, time 3001ms";
        String regex = "(\\d+)%";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            System.out.println("Packet loss: " + matcher.group(1));
        } else {
            System.out.println("No match found.");
        }*/
    }


}